import * as Cesium from "cesium"
// 导入图片路径
const imageUrl = new URL("./soil.jpg", import.meta.url)

interface ExcavationOptions {
  textureMap?: string //指定纹理贴图,
  tilesets?: Cesium.Cesium3DTileset[]
}

/**
 * @description 地形开挖
 * @example
    //实例化开挖工具
    excavationTool = new Excavation(viewer, {
      tilesets:[tileset]
    })
 */
export class Excavation {
  tilesets: Cesium.Cesium3DTileset[] = []
  textureMap: string | URL
  wallAndBottomEntities: Cesium.Entity[] = []
  constructor(
    public viewer: Cesium.Viewer,
    options: ExcavationOptions,
  ) {
    const { tilesets = [], textureMap = imageUrl } = options
    this.tilesets = tilesets
    this.textureMap = textureMap
  }
  /**
   * @param polygon //开挖范围(多边形)
   * @param digDepth //开挖深度(单位：米)
   * @returns
   */
  excavation(polygon: Cesium.Cartesian3[], digDepth: number) {
    if (polygon instanceof Array && polygon.length < 3) {
      console.error("地形开挖参数错误,多边形顶点小于3:", polygon)
      return
    }
    //根据开挖深度计算底部多边形
    const bottomPolygon = polygon.map((item) => {
      const cartographicPosition = Cesium.Cartographic.fromCartesian(item)
      cartographicPosition.height = cartographicPosition.height - digDepth
      return Cesium.Cartesian3.fromRadians(
        cartographicPosition.longitude,
        cartographicPosition.latitude,
        cartographicPosition.height,
      )
    })

    //计算裁剪多边形
    const clippingPolygon = new Cesium.ClippingPolygon({
      positions: bottomPolygon,
    })

    //3dtiles裁剪
    this.tilesets.forEach((item) => {
      if (!item.clippingPolygons)
        item.clippingPolygons = new Cesium.ClippingPolygonCollection()
      item.clippingPolygons.add(clippingPolygon)
    })

    //地形裁剪
    if (!this.viewer.scene.globe.clippingPolygons) {
      this.viewer.scene.globe.clippingPolygons =
        new Cesium.ClippingPolygonCollection()
    }
    this.viewer.scene.globe.clippingPolygons.add(clippingPolygon)

    //绘制底部贴图
    const bottom = this.viewer.entities.add({
      polygon: {
        hierarchy: bottomPolygon,
        material: new Cesium.ImageMaterialProperty({
          image: "/textures/soil.jpg",
        }),
        perPositionHeight: true,
      },
    })
    this.wallAndBottomEntities.push(bottom)

    //绘制墙面
    const surfacePolygon = polygon
    const length = bottomPolygon.length
    for (let i = 0; i < length; i++) {
      let wallPolygon = undefined
      if (i === 0) {
        wallPolygon = [
          surfacePolygon[i],
          bottomPolygon[i],
          bottomPolygon[length - 1],
          surfacePolygon[length - 1],
        ]
      } else {
        wallPolygon = [
          surfacePolygon[i],
          bottomPolygon[i],
          bottomPolygon[i - 1],
          surfacePolygon[i - 1],
        ]
      }
      const wall = this.viewer.entities.add({
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy(wallPolygon),
          material: new Cesium.ImageMaterialProperty({
            image: "/textures/soil.jpg",
          }),
          perPositionHeight: true,
        },
      })
      this.wallAndBottomEntities.push(wall)
    }
  }

  /**
   * @description 开挖恢复
   */
  recover() {
    console.log("recover")
    //移除裁剪面
    this.tilesets.forEach((item) => {
      if ("inverse" in item.clippingPolygons) {
        item.clippingPolygons.inverse = false
      }
      item.clippingPolygons.removeAll()
    })
    if ("inverse" in this.viewer.scene.globe.clippingPolygons) {
      this.viewer.scene.globe.clippingPolygons.inverse = false
    }
    this.viewer.scene.globe.clippingPolygons.removeAll()
    //删除实体
    this.wallAndBottomEntities.forEach((item) =>
      this.viewer.entities.remove(item),
    )
  }

  /**
   * @description 裁剪反转
   */
  reverse() {
    console.log("recover")
    this.tilesets.forEach((item) => {
      if (item.clippingPolygons) {
        ;(item.clippingPolygons as any).inverse = !!!(
          item.clippingPolygons as any
        ).inverse
      }
    })
    if (this.viewer.scene.globe.clippingPolygons.length > 0) {
      ;(this.viewer.scene.globe.clippingPolygons as any).inverse = !!!(
        this.viewer.scene.globe.clippingPolygons as any
      ).inverse
    }
  }
}
